/*
 * @Author: 晴鸢. 3013433857@qq.com
 * @Date: 2025-10-15 16:48:11
 * @LastEditors: 晴鸢. 3013433857@qq.com
 * @LastEditTime: 2025-10-30 22:55:11
 * @FilePath: /Learn/tcp/TcpServer.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
/*
 * @Author: 晴鸢. 3013433857@qq.com
 * @Date: 2025-10-15 16:48:11
 * @LastEditors: 晴鸢. 3013433857@qq.com
 * @LastEditTime: 2025-10-17 16:55:02
 * @FilePath: /Learn/tcp/TcpServer.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#include "Log.hpp"
#include"Thread.hpp"
#include"Task.hpp"
#include"Daemon.hpp"
const int defaultfd = -1;
const std::string defaultip = "0.0.0.0";
const int backlog = 10; // 后面解释

enum
{
    UsageError = 1,
    SocketError,
    BindError,
    ListenError
};
class TcpServer;
class ThreadData
{
public:
    ThreadData(int fd, const std::string &ip,  uint16_t &port, TcpServer*Server)
        : _sockfd(fd)
        , _clientip(ip)
        , _clientport(port)
        ,_server(Server)
    {}

public:
    int _sockfd;
    std::string _clientip;
    uint16_t _clientport;
    TcpServer* _server;//解决类内静态函数调用类内非静态函数
};

class TcpServer
{
public:
    TcpServer(const uint16_t &port, const std::string &ip = defaultip)
        : _listensockfd(defaultfd)
        , _ip(ip)
        , _port(port)
    {}
    /*
    static void *Routine(void *args)
    {
        pthread_detach(pthread_self()); // 设为分离状态，主线程无需阻塞等待
        ThreadData *td = static_cast<ThreadData *>(args);
        td->_server->Service(td->_sockfd,td->_clientip,td->_clientport);
        delete td;
        return nullptr;
    }
    */

    void Start()
    {
        lg.Enable(Classfile);
        Daemon();//出来时变为守护进程
        signal(SIGPIPE,SIG_IGN);//避免向未知的sockfd中写入而导致服务器关闭
        ThreadPool<Task>::GetInstance()->start();//启动线程池
        // signal(SIGCHLD,SIG_IGN); 直接忽略子进程信号也可以实现连续执行
        //  服务器需一直处于运行状态
        lg(Info, "tcpServer is running...");
        while (true)
        {
            // 1.获取新连接
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            // 返回新的套接字描述符，用于与客户端通信(连接套接字)
            int sockfd = accept(_listensockfd, (sockaddr *)&client, &len); // 阻塞式等待
            if (sockfd < 0)
            {
                lg(Fatal, "errno:%d,errstring:%s", errno, strerror(errno));
                continue;
            }
            uint16_t clientport = ntohs(client.sin_port);
            char clientip[32];
            inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));
            // 2.根据新连接进行通信
            lg(Info, "get a new link...,sockfd:%d,clientport:%d,clientip:%s", sockfd, clientport, clientip);

            //version2 多线程版
            //ThreadData *td = new ThreadData(sockfd, clientip, clientport,this);
            //pthread_t pid;
            //pthread_create(&pid, nullptr, Routine, td);
            //无需阻塞式等待
            //version3 线程池版
            Task t(sockfd,clientip,clientport);
            ThreadPool<Task>::GetInstance()->Push(t);
        }
    }
    /*
    void Service(int sockfd, const std::string &clientip, const uint16_t &clientport)
    {
        char message[4096];
        while (true)
        {
            ssize_t n = read(sockfd, message, sizeof(message));
            if (n > 0)
            {
                message[n] = 0;
                std::cout << "client say:#" << message << std::endl;
                std::string str = "server echo#";
                str += message;
                write(sockfd, str.c_str(), str.size());
            }
            else if (n == 0)
            {
                lg(Info, "%s:%d quit,server close sockfd:%d", clientip.c_str(), clientport, sockfd);
                break;
            }
            else
            {
                lg(Warning, "read error,sockfd:%d,clientport:%d,clientip:%s", sockfd, clientport, clientip);
                break;
            }
        }
    }
    */
    void Init()
    {
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0); // tcp协议
        if (_listensockfd < 0)
        {
            lg(Fatal, "create socket errno:%d,errstring:%s", errno, strerror(errno));
            exit(SocketError);
        }

        //允许端口复用 否则TIME_WAIT状态时会阻塞(防止偶发性的服务器无法立即重启)
        int opt = 1;
        setsockopt(_listensockfd, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &opt, sizeof(opt));

        lg(Info, "create socket success,listensockfd:%d", _listensockfd);
        // 初始化tcp套接字
        struct sockaddr_in local;
        bzero(&local, 0); //?
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        inet_aton(_ip.c_str(), &(local.sin_addr));
        int n = bind(_listensockfd, (sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            lg(Fatal, "bind errno:%d,errstring:%s", errno, strerror(errno));
            exit(BindError);
            pthread_t a;
        }
        lg(Info, "bind socket success,listensock:%d", _listensockfd);
        // Tcp是面向连接的，其服务器一般较为被动
        if (listen(_listensockfd, backlog) < 0)
        {
            lg(Fatal, "listen error,errno:%d,errstring:%s", errno, strerror(errno));
            exit(ListenError);
        }
        lg(Info, "listen socket success,listensock:%d", _listensockfd);
    }
    ~TcpServer()
    {
        if (_listensockfd > 0)
            close(_listensockfd);
    }

private:
    int _listensockfd; // 监听套接字
    uint16_t _port;
    std::string _ip;
};